/**
 * 
 */
package model.session;


/**
 * Represent a session. This means a succesions of event, basically solver or preprocessor execution
 * on a beginning CNF that lead to other execution on the cnf that result from the previous
 * execution ...
 * 
 * @author GRONOWSKI Stephane svan001@aol.com
 * 
 *         igsat 2010
 * 
 */
public class Session {

	private CNFUse	first;

	/**
	 * Create a session using the specified {@link CNFUse} as first block.
	 * 
	 * @param first
	 *            the cnf to use
	 */
	public Session(CNFUse first) {
		// TODO Auto-generated constructor stub
		this.first = first;
	}

	/**
	 * @return the first CNFUse.
	 */
	public CNFUse getFirst() {
		return first;
	}

	/**
	 * Return if this session contains the specified CFNUse.
	 * 
	 * @param cnf
	 *            a cnf
	 * @return if this session contains the specified CFNUse.
	 */
	public boolean containsCNFUse(CNFUse cnf) {
		return contains(first, cnf);
	}

	private boolean contains(CNFUse seekIn, CNFUse isseek) {
		if (seekIn == isseek)
			return true;
		for (CNFUse p : seekIn.getPreproc().values())
			if (contains(p, isseek))
				return true;

		return false;

	}

	/**
	 * Return the {@link CNFUse} that contains the specified {@link SolverExecutionBlock}.
	 * 
	 * @param solver
	 *            the {@link SolverExecutionBlock} to seek
	 * @return the {@link CNFUse} that contains it or null
	 */
	public CNFUse containsSolver(SolverExecutionBlock solver) {
		return containsSolver2(first, solver);
	}

	private CNFUse containsSolver2(CNFUse seekIn, SolverExecutionBlock solver) {
		if (seekIn.getSolver().contains(solver))
			return seekIn;
		for (CNFUse p : seekIn.getPreproc().values())
		{
			CNFUse res = containsSolver2(p, solver);
			if (res != null)
				return res;
		}
		return null;

	}

	/**
	 * Return the {@link CNFUse} that contains the specified {@link PreprocessorExecutionBlock}.
	 * 
	 * @param preproc
	 *            the {@link PreprocessorExecutionBlock} to seek
	 * @return the {@link CNFUse} that contains it or null
	 */
	public CNFUse containsPreprocessor(PreprocessorExecutionBlock preproc) {
		return containsPreprocessor2(first, preproc);
	}

	private CNFUse containsPreprocessor2(CNFUse seekIn, PreprocessorExecutionBlock preproc) {
		if (seekIn.getPreproc().keySet().contains(preproc))
			return seekIn;
		for (CNFUse p : seekIn.getPreproc().values())
		{
			CNFUse res = containsPreprocessor2(p, preproc);
			if (res != null)
				return res;
		}
		return null;

	}


	/**
	 * Close the session, means basically close all the cnf.
	 * 
	 * @return false if there was a problem.
	 */
	public boolean close() {
		return closeCNFUse(first);
	}

	/**
	 * Close the {@link CNFUse}, means basically close all the cnf associate.
	 * 
	 * @param cnf
	 *            the {@link CNFUse} to close
	 * @return false if there was a problem.
	 */
	public boolean closeCNFUse(CNFUse cnf) {
		if (cnf == null)
			return true;

		boolean res = true;
		if (!cnf.getCnf().close())
			res = false;

		for (CNFUse tmp : cnf.getPreproc().values())
			if (!closeCNFUse(tmp))
				res = false;

		return res;
	}

}
